#include "PWMControl.h"

#include "Timer.h"

struct _PWMControl
{
        Timer     parent_instance;
        uint16_t  h_value;
        uint16_t  l_value;
        uint16_t  scaler;
        uint16_t *duty_cycle;
        bool      is_enabled;
};

static bool       is_inited = false;
static PWMControl global_pwm_control;

PWMControl *
pwm_control_new_from_global(void)
{
        if (is_inited)
                return &global_pwm_control;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO |
                                       RCC_APB2Periph_TIM1,
                               ENABLE);
        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM1, ENABLE);
        GPIO_InitTypeDef gpio = {.GPIO_Mode  = GPIO_Mode_AF_PP,
                                 .GPIO_Pin   = GPIO_Pin_1,
                                 .GPIO_Speed = GPIO_Speed_50MHz};
        GPIO_Init(GPIOB, &gpio);

        TIM_TimeBaseInitTypeDef tim = {
                .TIM_Prescaler         = 71, // 示例值，72MHz/(71+1)=1MHz
                .TIM_CounterMode       = TIM_CounterMode_Up,
                .TIM_Period            = 999, // PWM周期为(999+1)/1MHz = 1ms
                .TIM_ClockDivision     = 0,
                .TIM_RepetitionCounter = 0 // 高级定时器特有
        };
        TIM_TimeBaseInit(TIM1, &tim);

        TIM_OCInitTypeDef ocs = {
                .TIM_OCMode = TIM_OCMode_PWM2,
                .TIM_OutputState =
                        TIM_OutputState_Disable, // 主通道禁用（使用互补通道）
                .TIM_OutputNState = TIM_OutputNState_Enable, // 使能互补输出
                .TIM_Pulse        = 0, // 占空比50%（CCR3=500）
                .TIM_OCPolarity   = TIM_OCPolarity_High,
                .TIM_OCNPolarity  = TIM_OCNPolarity_High,
                .TIM_OCIdleState  = TIM_OCIdleState_Reset,
                .TIM_OCNIdleState = TIM_OCNIdleState_Reset};
        TIM_OC3Init(TIM1, &ocs);

        TIM_CtrlPWMOutputs(TIM1, ENABLE);
        TIM_Cmd(TIM1, ENABLE);

        global_pwm_control.duty_cycle = NULL;
        //
        is_inited = true;
        return &global_pwm_control;
}

void
pwm_control_connect_duty_cycle(PWMControl *self, uint16_t *duty_cycle)
{
        self->duty_cycle = duty_cycle;
}

/**
 * @brief 设置 PWM 输出占空比，0 - 1000
 */
inline void
pwm_control_set_pwm_percent(uint16_t p_percent)
{
        if (p_percent > 1000)
                p_percent = 1000;
        TIM_SetCompare3(TIM1, p_percent);
}

void
pwm_control_start(PWMControl *self)
{
        self->is_enabled = true;
        TIM_SetCompare3(TIM1, 1);
}

void
pwm_control_set_duty_cycle(PWMControl *self, uint16_t duty_cycle)
{
        if (self->is_enabled)
                pwm_control_set_pwm_percent(duty_cycle);
        else
                TIM_SetCompare3(TIM1, 0);
}

void
pwm_control_stop(PWMControl *self)
{
        self->is_enabled = false;
        if (self->duty_cycle)
                *self->duty_cycle = 0;
        TIM_SetCompare3(TIM1, 0);
}

void
pwm_control_adjust_scale_reset(PWMControl *self)
{
        self->scaler  = 500;
        self->l_value = 0;
        self->h_value = 1000;
}

void
pwm_control_auto_adjust(PWMControl *self,
                        const float v_set,
                        const float v_actual)
{
        /**
         * v_actual 测量值小于 v_set 设定值时，增加占空比，反之减少。
         * 使用二分法最快找到符合设定值的占空比。
         */
        if (v_actual > v_set)
                self->h_value = self->scaler;
        else if (v_actual < v_set)
                self->l_value = self->scaler;
        self->scaler = self->l_value + (self->h_value - self->l_value) / 2;
        pwm_control_set_pwm_percent(self->scaler);

        /* 确保高标尺小于低标尺 */
        if (self->h_value < self->l_value)
                self->h_value = self->l_value;
}
